﻿/* 文件名称： jquery.listview.js
 * 文件描述：基于jquery和和HTML5（data-attribuate）的列表插件：
 *      1、提供基于注册的扩展机制，用于对插件进行扩展
 *      2、提供了一定的默认功能以方便进行操作
 * 作者：赤菁风铃、清月荷雾
 * 创建时间：2013年07月27日 16:16:44
 * 依赖：jquery >= 1.71 jquery.form >= 3.1.4 jquery.artDialog > 4.0 jquery.validate > 2.0
 * 使用说明：
 *      1、默认保留role、event和url三个data-attribuate，请不要尝试对他们进行扩展
 *      2、所有的事件都是以role属性发起的，即当event事件触发时，执行role属性绑定的函数
 *      3、在HTML中书写时，请添加写成data-前缀，在JS中绑定时，直接使用属性名
 *      4、系统使用head、target、listid、parent四种特殊的role来标识列表的刷新方式，和列表之间的跳转关系请不要为其添加事件
 *      5、系统中默认注册了几个role属性给大家使用，请尽量避免使用
 */

(function ($) {
    if ($.listView && $.listView.version) {
        return;
    }
    //用于修正一些版本的JQUERY没有isArray方法的问题
    $.isArray = $.isArray || function (value) {
        return Object.prototype.toString.call(value) === '[object Array]';
    };
    //用于进行全局设置的对象
    var list = $.listView = {
        _backUp: $.listView
    };
    $.extend(list, {
        version: "0.2.0",//版本号
        actions: {},//用于记录所有的响应函数
        attributes: ["role", "event", "url", "parent"],//用于注册向列表函数发送的属性，指向其它的data属性，写在这里面的为默认注册的属性
        parentList: {},//用于存放所有的相关
        defaultSettings: { //用于进行全局设置的对象
            allowSubmit: false,//是不是允许列表中的所有表单提交(如果是则submit事件会造成页面的刷新)
            firstLoad: false,//第一次进入页面是不是刷新数据
            type: "get"//获取数据的方式
        },
        createAction: function (obj) {//用于注册data-role属性所指向的事件,重复的会进行覆盖
            //obj中每一属性对应的函数为function(views, attrs, e){}
            //其中views表示对应列表的所有相关定义页面
            //  root：生成列表时的根，即调用listView函数时使用的元素
            //  content：列表内容区，当显示子页面时，列表内容区会进行隐藏
            $.extend(this.actions, obj);
        },
        createAttribute: function (obj) {//用于注册其它的data属性
            if (typeof obj === 'string') {
                this.attributes.push(obj);
            } else if ($.isArray(obj)) {
                $.merge(this.attributes, obj);
            }
            var ret = [], done = {};
            try {
                for (var i = 0, length = this.attributes.length; i < length; i++) {
                    if (!done[this.attributes[i]]) {
                        done[this.attributes[i]] = true;
                        ret.push(this.attributes[i]);
                    }
                }
            } catch (e) {
                ret = this.attributes;
            }
            this.attributes = ret;
        },
        setDefault: function (obj) {//修改全局默认值
            $.extend(this.defaultSettings, obj);
        },
        tools: {//工具函数，用于进行子函数开发时使用
            nameBind: function (target) { //用于进行表单数据的缓存
                target.find("[name]").each(function () {
                    if (!$(this).attr("type") || $(this).attr("type") !== 'hidden') {
                        $(this).attr("bindname", $(this).attr("name"));
                        $(this).after("<input type='hidden' name='" + $(this).attr("name") + "'value='" + $(this).val() + "'/>");
                        $(this).removeAttr("name");
                    }
                });
            },
            nameReview: function (target, backway) {//对已经绑定的表单进行重新绑定，如果backway为true，则把缓存重新赋予输入框，否则把输入框赋给缓存
                if (backway) {
                    target.find("[name]").each(function () {
                        target.find("[bindname=" + $(this).attr("name") + "]").val($(this).val());
                    });
                } else {
                    target.find("[bindname]").each(function () {
                        target.find("[name=" + $(this).attr("bindname") + "]").val($(this).val());
                    });
                }
            },
            eventBind: function (target, currentid) {//用于进行事件绑定(更新了dom以后应当对更新的部分进行重新绑定)
                //这里进行事件绑定时使用的了data-role和data-event属性
                //绑定结果为data-role对应的控件的data-event所对应的事件绑定了list.actions[role]函数
                target.find("[data-role]").each(function () {
                    var jqid = $(this).attr("jqid");
                    var parents = parseInt($(this).attr("data-parent") || "0") || 0;//取出元素的父级元素
                    var current = currentid;
                    for (var i = 0; i < parents; i++) {
                        if (list.parentList[current].parent) {
                            current = list.parentList[current].parent;
                        }
                    }
                    if (!jqid) {
                        $(this).attr("jqid", current);
                    } else {
                        return;
                    }
                    var attrs = {};
                    for (var x in list.attributes) {
                        attrs[list.attributes[x]] = $(this).attr("data-" + list.attributes[x]);
                    }
                    var role = attrs.role || "";
                    var events = attrs.event || "click";
                    if (role in list.actions) {
                        $(this).bind(events, function (e) {
                            list.actions[role].call(this, current, attrs, e);
                        });
                    }
                });
            }
        }
    });
    //扩展JQUERY函数
    $.fn.extend({
        listView: function (options) { //把一个元素装饰成一个异步刷新列表
            options = $.extend({}, list.defaultSettings, options);
            $(this).each(function () {
                var root = $(this)//根节点
                    , content //原始内容节点
                    , frame = $(options.frame || "<div style='display: none;position:absolute;width:100%;height:100%; top:0;left:0;'>")//用于显示子内容的层
                    , target = root.find("[data-role=target]") //列表刷新区域
                    , head = root.find("[data-role=head]");//列表刷新目标
                //处理root、content、frame、target、head节点
                if (!root.css("position") || root.css("position") === "static") {
                    root.css("position", "relative");
                }
                root.wrapInner("<div>");
                content = $(root.children("div")[0]);
                $.each(list.attributes, function (key, value) {
                    content.attr("data-" + value, root.attr("data-" + value));
                });
                content.after(frame);
                var rootparent = root.closest("[data-listid]");
                var parentid = null;
                if (rootparent.length > 0) {
                    parentid = $(rootparent[0]).attr("data-listid") || null;
                }
                var rootid = "jqlv" + Number(new Date()).toString().replace(".", "");
                root.attr("data-listid", rootid);
                //相关页面处理
                var views = {
                    id: rootid,//当前列表的ID
                    parent: parentid,//当前列表的父亲ID
                    root: root,//列表的根元素
                    content: content,//列表的内容元素
                    frame: frame,//列表的浮出层元素
                    target: target,//列表的刷新目标
                    head: head,//列表的查询条件列表
                    options: options,//配置参数
                    refresh: function () {
                        content.listSubmit(content.attr("data-url"), {
                            type: "post",
                            cache: false,
                            target: target
                        }, function () {
                            list.tools.eventBind(target, rootid);
                        });
                    }
                };
                list.parentList[rootid] = views;
                //如果用户需要，阻止所有表单提交
                if (!options.allowSubmit) {
                    root.delegate("form", "submit", function () {
                        return false;
                    });
                }
                //默认事件绑定
                list.tools.eventBind(content, rootid);
                //加载第一次数据
                if (options.firstLoad) {
                    content.listSubmit(function () {
                        list.tools.eventBind(target);
                    });
                }
            });
        },
        listSubmit: function (url, options, callBack) { //异步提交一个元素或者控件
            if (typeof options === 'function') {
                callBack = options;
                options = {};
            }
            options = options || {};
            var defaultsetting = list.defaultSettings,
                type = options.type || defaultsetting.type,
                target = options.target || $(false),
                isform = $(this).is("form"),
                self = $(this),
                container = self;
            if (!isform) {
                self.wrap("<form></form>");
                container = self.parent();
            }
            container.ajaxSubmit({
                url: url,
                cache: false,
                type: type,
                target: target,
                success: callBack || function () {
                },
                error: function () {
                    alert("获取数据失败");
                },
                complete: function () {
                    if (!isform) {
                        self.unwrap();
                    }
                }
            });
        },
        vtip: function () {
            var self = $(this);
            var xOffset = -20; // x distance from mouse
            var yOffset = 20; // y distance from mouse
            self.find(":input").each(function () {
                $(this).mouseover(function (e) {
                    var tip = null;
                    if ($(this).hasClass("form-list-item-warn") && $(this).attr("data-tips")) {
                        tip = '<span id="vtip" class="error"><span class="vtip_arrow"></span>' + $(this).attr("data-tips") + '</top>';
                    } else if ($(this).attr("data-tip")) {
                        tip = '<span id="vtip"><span class="vtip_arrow"></span>' + $(this).attr("data-tip") + '</top>';
                    }
                    if (tip) {
                        $("#vtip").remove();
                        var top = (e.pageY + yOffset);
                        var left = (e.pageX + xOffset);
                        tip = $(tip);
                        tip.css("top", top + "px").css("left", left + "px");
                        $("body").append(tip);
                        if ($.fn.bgiframe) {
                            tip.bgiframe();
                        }
                    }
                });
                $(this).mouseout(function (e) {
                    $("#vtip").remove();
                });
            });
            return self;
        },
        formset: function (index) {
            //region 标签页初始化
            //缓存并初始化header
            var headers = $(this).find(".count-header").children("a");
            headers.eq(index - 1).addClass("active");
            //缓存并初始化children
            var children = $(this).find(".count-content-group").children("div");
            if (children.length > 1) {
                children.each(function (i) {
                    if (i != index - 1) {
                        $(this).hide();
                    }
                });
            }
            //绑定标签切换效果
            headers.each(function (index) {
                $(this).click(function () {
                    if ($(this).hasClass("active")) {
                        return false;
                    }
                    children.hide().eq(index).fadeIn();
                    headers.removeClass("active");
                    $(this).addClass("active");
                });
            });
            //endregion
            return self;
        }
    });
    list.createAttribute("type index message inline".split(' '));
    list.createAction({
        refresh: function (id, attrs, e) {//刷新列表和搜索条件
            var views = list.parentList[id];
            var options = $.extend({}, views.options, {
                type: attrs.type || views.options.type,
                cache: false
            });
            list.tools.nameReview(views.head, false);
            views.refresh();
        },
        view: function (id, attrs, e) {//弹出一个新的页面
            if (attrs.message && !confirm(attrs.message)) {
                return false;
            }
            var views = list.parentList[id];
            $.ajax({
                cache: false,
                type: attrs.type || views.options.type || "get",
                url: attrs.url || location.href,
                data: attrs.inline === "true" ? {} : views.content.find("[name]").fieldSerialize(),
                error: function () {
                    alert("获取数据失败");
                },
                success: function (data) {
                    if (typeof data != "string") {
                        return alert(data.message || "操作失败");
                    }
                    $(views.frame).html(data);
                    $(views.frame).show();
                    $(views.content).hide();
                    $.listView.tools.eventBind(views.frame, id);
                }
            });
        },
        dialog: function (id, attrs, e) {//弹出一个新的页面
            if (attrs.message && !confirm(attrs.message)) {
                return false;
            }
            var views = list.parentList[id];
            var tags = views.content.find("[name]");
            $.ajax({
                cache: false,
                type: attrs.type || views.options.type || "get",
                url: attrs.url || location.href,
                data: attrs.inline === "true" ? {} : views.content.find("[name]").fieldSerialize(),
                error: function () {
                    alert("获取数据失败");
                },
                success: function (data) {
                    if (typeof data != "string") {
                        return alert(data.message || "操作失败");
                    }
                    var content = $(data);
                    $.listView.tools.eventBind(content, id);
                    var dialog = $.dialog({
                        title: '图片选择',
                        content: data,
                        onclose: function () {
                            views.refresh();
                        }
                    });
                    dialog.showModal();
                }
            });
        },
        action: function (id, attrs, e) {//执行一个ajax请求执行操作
            if (attrs.message && !confirm(attrs.message)) {
                return false;
            }
            var views = list.parentList[id];
            $.ajax({
                cache: false,
                type: attrs.type || views.options.type || "get",
                url: attrs.url || location.href,
                data: attrs.inline === "true" ? {} : views.content.find("[name]").fieldSerialize(),
                error: function () {
                    alert("获取数据失败");
                },
                success: function (data) {
                    if (data.success) {
                        views.refresh();
                    }
                    else {
                        var d = $.dialog({
                            content: "<div class='dialog-error-message'><div class='dialog-error-title'>您的提交没有成功，可能的原因如下:</div><div class='dialog-error-content'>" + data.message + "</div></div>",
                            title: "操作提示"
                        });
                        d.showModal();
                    }
                }
            });
        },
        back: function (id, attrs, e) {//隐藏新页面返回列表
            var views = list.parentList[id];
            $(views.frame).hide();
            $(views.content).show();
            $(views.frame).html("");
        },
        form: function (id, attrs, e) {//子表单提交（注意请绑定data-event=submit）
            if (attrs.message && !confirm(attrs.message)) {
                return false;
            }
            var views = list.parentList[id];
            $(this).listSubmit(attrs.url, {
                target: $("<div sytle='display:none;'></div>"),
                type: attrs.type || views.options.type,
                cache: false
            }, function (data) {
                if (data.success) {
                    $(views.frame).hide();
                    $(views.content).show();
                    views.refresh();
                } else {
                    var d = $.dialog({
                        content: "<div class='dialog-error-message'><div class='dialog-error-title'>您的提交没有成功，可能的原因如下:</div><div class='dialog-error-content'>" + data.message + "</div></div>",
                        title: "操作提示"
                    });
                    d.showModal();
                }
            });
            return false;
        },
        pager: function (id, attrs, e) {//用于进行翻页
            var views = list.parentList[id];
            if (attrs.index) {
                $(views.root).find("[name=PageIndex]").val(attrs.index);
            }
            views.refresh();
        }
    });
})(jQuery);
